package storage.v1;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.onpositive.wikistorage.PictureManager;

public class PictureDataStorage {
	
	private final static String storageFilePath_default = "C:/wikistorage/" ;
	private final static String storageFile = "picture-data.xml" ;
	private final String storageFilePath ;
	
	HashMap<String,PictureCollection> pictureSet = new HashMap<String, PictureDataStorage.PictureCollection>() ;
	
	public static class PictureCollection{
		
		final String docName ;
		ArrayList<PictureData> dataArray = new ArrayList<PictureDataStorage.PictureData>() ;
		
		public PictureCollection( String docName) {
			super();
			this.docName = docName ;
		}

		public void addPicture( String picName, String localPath, String wwwPath, String description) {
			
			dataArray.add( new PictureData(picName, localPath, wwwPath, description) ) ;
		}

		public String getDocName() {
			return docName;
		}

		public PictureData getPictureData(String name) {
			
			for( PictureData pd : dataArray )
				if( pd.getPictureName().equals(name) )
					return pd ;
			
			return null ;
		}

		public ArrayList<PictureData> getDataArray() {
			return dataArray;
		}
	}
	
	public static class PictureData{
		
		public PictureData(String pictureName, String localPath,
				String wwwPath, String description) {
			super();
			this.pictureName = pictureName != null ? pictureName : "" ;
			this.localPath = localPath != null ? localPath : "" ;
			this.wwwPath = wwwPath != null ? wwwPath : "" ;
			this.description = description != null ? description : "";
		}
		
		private final String pictureName ;		
		private final String localPath ;		
		private final String wwwPath ;
		private final String description ;
		
		public String getPictureName() {
			return pictureName;
		}
		public String getLocalPath() {
			return localPath;
		}
		public String getWwwPath() {
			return wwwPath;
		}
		public String getDescription() {
			return description;
		}
		
	}
	
	public PictureDataStorage(String rootPath) {
		this.storageFilePath = (rootPath != null ? PictureManager.constructPicturePath(rootPath) : storageFilePath_default) + storageFile ;
		loadData() ;
	}



	private final static String ROOT_ELEMEENT_NAME = "pictures-list" ;
	private final static String PICTURE_ELEMENT_NAME = "picture" ;
	private final static String DOCUMENT_ELEMENT_NAME = "document" ;
	
	public void loadData()
	{
		DocumentBuilder builder ;		
		try {
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder() ;
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			return;
		}
		
		Document document ;
		
		try {
			document = builder.parse( new FileInputStream(new File( storageFilePath ) ) ) ;
		} catch (FileNotFoundException e) {
			//e.printStackTrace();
			return;
		} catch (SAXException e) {
			e.printStackTrace();
			return;
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}

		Element root = document.getDocumentElement() ;		
		NodeList rootList = root.getChildNodes() ;
		
		int l0 = rootList.getLength() ;
		for( int i = 0 ; i < l0 ; i++ )
		{
			Node n0 = rootList.item(i);
			if( !(n0 instanceof Element) )
				continue ;
			
			String elementName = n0.getNodeName() ;
			Element levelOneElement = (Element)n0 ;
			if( elementName.equals(ROOT_ELEMEENT_NAME) ){				
					
				NodeList nodeList = levelOneElement.getChildNodes() ;
				int l1 = nodeList.getLength() ;
				for( int j = 0 ; j < l1 ; j++ )
				{
					Node n1 = nodeList.item(j);
					if( n1 instanceof Element )
					{
						Element elem = (Element)n1 ;
						String eName = elem.getNodeName() ;
						String valueString = elem.getAttribute("value") ;
						if( valueString != null && valueString.length() != 0 )
						{
							if( !eName.equals(DOCUMENT_ELEMENT_NAME) )
								continue ;
							
							processDocumentElement( elem ) ;														
						}
					}					
				}
			}			
		}		
	}
	
	private final static String ATTR_DOCUMENT_NAME = "name" ;
	private final static String ATTR_PICTURE_NAME="name" ;
	private final static String ATTR_DESCRIPTION = "description" ;
	private final static String ATTR_LOCAL_PATH = "local-path" ;
	private final static String ATTR_WWW_PATH = "www-path" ;
	private void processDocumentElement(Element docElement )
	{
		PictureCollection picData = null ;
		String docName = docElement.getAttribute( ATTR_DOCUMENT_NAME) ;
		NodeList nodeList = docElement.getChildNodes() ;
		int l1 = nodeList.getLength() ;
		for( int j = 0 ; j < l1 ; j++ )
		{
			Node n1 = nodeList.item(j);
			if( n1 instanceof Element )
			{
				Element elem = (Element)n1 ;
				String eName = elem.getNodeName() ;
				String valueString = elem.getAttribute("value") ;
				if( valueString != null && valueString.length() != 0 )
				{
					if( !eName.equals(PICTURE_ELEMENT_NAME) )
						continue ;
					
					String localPath = elem.getAttribute(ATTR_LOCAL_PATH) ;
					String wwwPath = elem.getAttribute(ATTR_WWW_PATH) ;
					String picName = elem.getAttribute(ATTR_PICTURE_NAME) ;
					String descriptopn = elem.getAttribute(ATTR_DESCRIPTION) ;
					
					if( localPath.length() == 0 && wwwPath.length() == 0 )
						continue ;
					
					if( picData == null )
					{
						picData = new PictureCollection(docName) ;
						pictureSet.put( docName, picData ) ;
					}
					picData.addPicture( picName, localPath, wwwPath, descriptopn ) ;					
				}
			}					
		}				
	}
	public void saveData()
	{
		DocumentBuilder builder ;		
		try {
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder() ;
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			return;
		}
		
		Document newDocument = builder.newDocument() ;
		Element rootElement = newDocument.createElement( ROOT_ELEMEENT_NAME );
		newDocument.appendChild( rootElement ) ;
		
		for( PictureCollection pd : pictureSet.values() )
		{
			String docName = pd.getDocName() ;
			Element docElement = newDocument.createElement( DOCUMENT_ELEMENT_NAME );
			docElement.setAttribute(ATTR_DOCUMENT_NAME, docName) ;
			rootElement.appendChild( docElement ) ;
			
			for( PictureData pdt : pd.getDataArray() )
			{
				String picName = pdt.getPictureName() ;
				String localPath = pdt.getLocalPath() ;
				String wwwPath = pdt.getWwwPath() ;
				String description = pdt.getDescription() ;
				
				Element picElement = newDocument.createElement( PICTURE_ELEMENT_NAME );				
				docElement.appendChild( picElement ) ;
				picElement.setAttribute(ATTR_PICTURE_NAME, picName ) ;
				picElement.setAttribute(ATTR_WWW_PATH, wwwPath) ;
				picElement.setAttribute(ATTR_LOCAL_PATH, localPath) ;							
				picElement.setAttribute(ATTR_DESCRIPTION, description) ;
			}
		}
		
		Transformer transformer ;
		try {
			transformer =  TransformerFactory.newInstance().newTransformer() ;
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
			return ;
		} catch (TransformerFactoryConfigurationError e){
			e.printStackTrace();
			return ;
		}
		transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
		
		Element root = newDocument.getDocumentElement() ;
		StreamResult sr = new StreamResult( new File( storageFilePath )) ;
		try {
			transformer.transform( new DOMSource(root),  sr ) ;
		} catch (TransformerException e) {
			e.printStackTrace();
			return ;
		}	
	}
	public PictureCollection getPictureData(String name) {		
		return pictureSet.get(name) ;
	}
	
	public void putPictureData(PictureCollection pd) {		
		pictureSet.put(pd.getDocName(), pd ) ;
	}

}
